home *** CD-ROM | disk | FTP | other *** search
/ Developer CD Series 1998…eptember: Technology Seed / September 98 ADC Seed CD.toast / FireWire 1.1 DR2 SDK / Source / FWiX / FWiXApp / FWiXdrag.c < prev    next >
Encoding:
C/C++ Source or Header  |  1998-01-15  |  22.5 KB  |  871 lines  |  [TEXT/MPS ]

  1. /*
  2.     File:        FWXDrag.c
  3.  
  4.     Contains:    Software to handle Finder drag copies onto FireWire File Exchange icons.
  5.  
  6.     Version:    1.0
  7.  
  8.     Written by:    Jay Lloyd
  9.  
  10.     Copyright:    © 1996-1997 by Apple Computer, Inc., all rights reserved.
  11.  
  12.     File Ownership:
  13.  
  14.         DRI:                Jay Lloyd
  15.  
  16.         Other Contact:        
  17.  
  18.         Technology:            FireWire
  19.  
  20.     Writers:
  21.  
  22.         (jkl)    Jay Lloyd
  23.  
  24.     Change History (most recent first):
  25.  
  26.       <FW14>     6/19/97    jkl        Made SendFSSpecListToSelf available globally for send
  27.                                     AppleScript command.
  28.       <FW13>     5/16/97    jkl        Disposed of region handle in HandleDragTracking.
  29.       <FW12>      5/7/97    jkl        Updated data structure field names.
  30.       <FW11>     4/29/97    jkl        Made sure node drag hiliting is clipped within the scroll bars
  31.                                     and window.
  32.        <10*>     4/23/97    jkl        Fix drag hiliting within scroll bars.
  33.       <FW10>     3/18/97    jkl        Changed drag hiliting to hilite node icon and name.
  34.        <FW9>     2/27/97    jkl        Updated drag receive routine to handle window scrolling.
  35.        <FW8>     2/19/97    jkl        Fixed a problem with GetNodeInfo returning bad error message.
  36.        <FW7>      2/2/97    jkl        Corrected the DragReceive routine to only recognize a drop in a
  37.                                     node rectangle.
  38.        <FW6>     1/27/97    jkl        Changed the HandleFSItems routine to call a routine to add the
  39.                                     items to a send check queue, instead of calling a preflight
  40.                                     check and attempting send..
  41.        <FW5>     1/16/97    jkl        Added user interface features for alpha candidate. Changed
  42.                                     window handling to normal window behavior and updated drag
  43.                                     tracking for this.
  44.        <FW4>      1/8/97    ES        Changed to use FWX nodes instead of FWX drivers.
  45.        <FW3>    11/13/96    jkl        Added accessor routines to get receive node name and node info
  46.                                     record.
  47.        <FW2>    10/31/96    jkl        Added code to start check for receiver node
  48.                                     being able to handle copy. Added support for
  49.                                     multiple file/folder drops. Changed drag
  50.                                     acceptance to not accept drag if copy in progress.
  51.        <FW1>     10/2/96    jkl        initial check-in, based on DTS FinderDrag
  52. */
  53.  
  54. #include <Types.h>
  55. #include <QuickDraw.h>
  56. #include <Files.h>
  57. #include <AppleEvents.h>
  58. #include <Drag.h>
  59. #include <Windows.h>
  60. #include <Devices.h>
  61. #include <Timer.h>
  62. #include <Icons.h>
  63.  
  64. #include "FWiX.h"
  65. #include "FWiXmain.h"
  66. #include "FWiXdrag.h"
  67.  
  68. #include <stdio.h>
  69. extern char  debugStr[256];
  70. static pascal void FWDebugStr(
  71.     ConstStr255Param            debuggerMsg)
  72. {
  73. #ifdef FW_DEBUG_BUILD
  74. #if FW_DEBUG_BUILD
  75.     DebugStr (debuggerMsg);
  76. #endif
  77. #endif
  78. }
  79.  
  80. //////////////////////////////////////////////////////////////////////////////
  81. //
  82. // Internal procedure prototypes.
  83. //
  84.  
  85. OSErr InstallDragHandlers (void);    
  86.  
  87. void RemoveDragHandlers (void);
  88.     
  89. static Boolean MouseIsInContentRgn (
  90.     DragReference            theDrag,
  91.     WindowPtr                pWin);
  92.  
  93. static Boolean DragItemsAreAcceptable (
  94.     DragReference            theDrag);
  95.     
  96. static pascal OSErr HandleDragTracking (
  97.     DragTrackingMessage        theMessage,
  98.     WindowPtr                pWin,
  99.     void                    *handlerRefCon,
  100.     DragReference            theDrag);
  101.  
  102. static pascal OSErr HandleDragReceive (
  103.     WindowPtr                pWin,
  104.     void                    *handlerRefCon, 
  105.     DragReference            theDrag);
  106.     
  107. OSErr GetNodeInfo (
  108.     FWXNodeID                nodeID,
  109.     RecvNodePtr                *pRecvNode);
  110.  
  111. OSErr GetNodeDragRect (
  112.     WindowPtr            pWin,
  113.     SInt16                spaceIndex,
  114.     Rect                *iconRect,
  115.     Rect                *textRect);
  116.     
  117. OSErr GetNodeName (
  118.     WindowPtr            pWin,
  119.     SInt16                spaceIndex,
  120.     StringPtr            *pString);
  121.     
  122. static SInt16 WhichRecvNode (
  123.     WindowPtr            pWin,
  124.     Point                localPt);
  125.     
  126. static void GetNodeIDFromIndex(
  127.     SInt16                nodeIndex,
  128.     FWXNodeID            *whichNode,
  129.     WindowPtr            pWin);
  130.  
  131. static void SendDropInWindowRecvNode (
  132.     WindowPtr            pWin,
  133.     DragReference        theDrag,
  134.     FSSpecPtr            pFSSpecList,
  135.     UInt16                numInList);
  136.  
  137. pascal OSErr HandleAEFileSpecList (
  138.     AppleEvent            *pAEvent,
  139.     AppleEvent             *pReply,
  140.     SInt32                refCon);
  141.     
  142. static void HandleDragHilite (
  143.     SInt16                theMessage,
  144.     Rect                *iconRect,
  145.     Rect                *textRect);
  146.         
  147. //////////////////////////////////////////////////////////////////////////////
  148. //
  149. // External procedure prototypes.
  150. //
  151.  
  152. extern OSErr HandleFSItem (
  153.     FSSpecPtr            pFSItem,
  154.     FWXNodeID            whichNode);
  155.  
  156. //////////////////////////////////////////////////////////////////////////////
  157. //
  158. //    Globals
  159. //
  160. extern FWXAppDataPtr gpFWXAppData;
  161.  
  162. //////////////////////////////////////////////////////////////////////////////
  163. //
  164. //    InstallDragHandlers
  165. //
  166. //    InstallDragHandlers attaches tracking and receive handlers to our
  167. //    application.
  168. //    
  169. //
  170.  
  171. OSErr InstallDragHandlers (void)
  172. {
  173.     DragTrackingHandlerUPP        pDragTracker = nil;
  174.     DragReceiveHandlerUPP        pDragReceiver = nil;
  175.     OSErr                         err = noErr;
  176.     
  177.     gpFWXAppData->dragReceiveHandlerInstalled = false;
  178.     gpFWXAppData->dragTrackingHandlerInstalled = false;
  179.     
  180.     //    Create and install the drag tracker
  181.     pDragTracker = NewDragTrackingHandlerProc(HandleDragTracking);
  182.     if (pDragTracker != nil) {
  183.         //    We allocated the procpointer, install it.
  184.         err = InstallTrackingHandler(pDragTracker, nil, nil);
  185.     
  186.         if (err == noErr) {
  187.             //    We installed the drag tracker.
  188.             gpFWXAppData->dragTrackingHandler = pDragTracker;
  189.             gpFWXAppData->dragTrackingHandlerInstalled = true;
  190.         } else {
  191.             //    The drag tracker was allocated but not installed,
  192.             //    dispose of the routine descriptor.
  193.             DisposeRoutineDescriptor(pDragTracker);
  194.             return err;
  195.         }
  196.     } else {
  197.         //    We could not allocate the proc pointer
  198.         return memFullErr;
  199.     }
  200.     
  201.     //    Create and install the drag receiver. If we got this far,
  202.     //    the drag tracker is installed.
  203.     pDragReceiver = NewDragReceiveHandlerProc(HandleDragReceive);
  204.     if (pDragReceiver != nil) {
  205.         //    We allocated the procpointer, install it.
  206.         err = InstallReceiveHandler(pDragReceiver, nil, nil);
  207.     
  208.         if (err == noErr) {
  209.             //    We installed the drag receiver.
  210.             gpFWXAppData->dragReceiveHandler = pDragReceiver;
  211.             gpFWXAppData->dragReceiveHandlerInstalled = true;
  212.         } else {
  213.             //    The drag receiver was allocated but not installed,
  214.             //    dispose of the routine descriptor, clean up the tracker.
  215.             DisposeRoutineDescriptor(pDragReceiver);
  216.             RemoveTrackingHandler(pDragTracker, nil);
  217.             DisposeRoutineDescriptor(pDragTracker);
  218.             gpFWXAppData->dragTrackingHandlerInstalled = false;
  219.             return err;
  220.         }
  221.     } else {
  222.         //    We could not allocate the proc pointer, clean up the tracker.
  223.         RemoveTrackingHandler(pDragTracker, nil);
  224.         DisposeRoutineDescriptor(pDragTracker);
  225.         gpFWXAppData->dragTrackingHandlerInstalled = false;
  226.         return memFullErr;
  227.     }
  228.             
  229.     return err;
  230. }
  231.  
  232.  
  233. //////////////////////////////////////////////////////////////////////////////
  234. //
  235. //    RemoveDragHandlers
  236. //
  237. //    Remove the drag handlers from a window prior to closing the window.
  238. //
  239.  
  240. void RemoveDragHandlers (void)
  241. {    
  242.     if (gpFWXAppData->dragReceiveHandlerInstalled) {
  243.         RemoveReceiveHandler(gpFWXAppData->dragReceiveHandler , nil);
  244.         DisposeRoutineDescriptor(gpFWXAppData->dragReceiveHandler);
  245.     }
  246.     
  247.     if (gpFWXAppData->dragTrackingHandlerInstalled) {
  248.         RemoveTrackingHandler(gpFWXAppData->dragTrackingHandler, nil);
  249.         DisposeRoutineDescriptor(gpFWXAppData->dragTrackingHandler);
  250.     }
  251. }
  252.  
  253.  
  254. //////////////////////////////////////////////////////////////////////////////
  255. //
  256. //    MouseInContentRgn
  257. //
  258. //    returns true if the mouse is in the content area of the window
  259. //    (not necessarily in the visible rgn)
  260. //
  261.  
  262. static Boolean MouseIsInContentRgn (
  263.     DragReference            theDrag,
  264.     WindowPtr                pWin)
  265. {
  266.     Point                    mousePt;
  267.     
  268.     GetDragMouse(theDrag, &mousePt, nil);
  269.     
  270.     return PtInRgn(mousePt, ((WindowPeek) pWin)->contRgn);
  271. }
  272.  
  273.  
  274. //////////////////////////////////////////////////////////////////////////////
  275. //
  276. //    DragItemsAreAcceptable
  277. //
  278. //    Returns true if the contents (data) of the drag
  279. //    are acceptable. Its a file or folder.
  280. //
  281. //    Called by the tracking and receive handlers
  282. //
  283.  
  284. static Boolean DragItemsAreAcceptable(
  285.     DragReference        theDrag)
  286. {
  287.     OSErr                err;
  288.     UInt16                numItems;
  289.     UInt16                indexItem;
  290.     ItemReference        itemRef;
  291.     FlavorFlags            theFlags;
  292.  
  293.     if (gpFWXAppData->pSenderWindow != FrontWindow())
  294.         return false;
  295.         
  296.     //    loop through each item in the drag to make sure it has an HFS flavor
  297.     err = CountDragItems(theDrag, &numItems);
  298.     if (err == noErr) {
  299.         for (indexItem = 1; indexItem <= numItems; indexItem++) {
  300.  
  301.             err = GetDragItemReferenceNumber(theDrag, indexItem, &itemRef);
  302.  
  303.             if (err == noErr) {
  304.                 err = GetFlavorFlags(theDrag, itemRef, flavorTypeHFS, &theFlags );
  305.                 if (err != noErr)
  306.                     return false;    // drag item is not hfs, its all or nothing
  307.             } else
  308.                 return false;        // could not get item reference
  309.         }
  310.     } else {
  311.         return false;                // could not count items
  312.     }
  313.         
  314.     return true;                    // each item is an hfs (should always be that way)
  315. }
  316.  
  317. //////////////////////////////////////////////////////////////////////////////
  318. //
  319. //    HandleDragTracking
  320. //
  321. //    Called by the drag manager whenever a drag is
  322. //    over one of our windows. On entry the current
  323. //    port has been set to our windows by the Drag Manager.
  324. //
  325.  
  326. static pascal OSErr HandleDragTracking (
  327.     DragTrackingMessage        theMessage,
  328.     WindowPtr                pWin,
  329.     void                    *handlerRefCon,
  330.     DragReference            theDrag)
  331. {
  332. //#pragma unused handlerRefCon
  333.     WindowDataPtr            pWinData;
  334.     RgnHandle                hOldClip;
  335.     Rect                    iconRect, textRect, drawRect;
  336.     Point                    localPt;
  337.     SInt16                    mouseInWhichSpace;
  338.     SInt16                    deltaH, deltaV;
  339.     OSErr                    err = noErr;
  340.     
  341.     switch (theMessage)
  342.     {    
  343.         case dragTrackingEnterHandler:            
  344.             // Initialization for the handler
  345.             (gpFWXAppData->dragHandlerGlobals).acceptableDragFlag = 
  346.                 DragItemsAreAcceptable(theDrag);
  347.             (gpFWXAppData->dragHandlerGlobals).hilitedSpace = kNoSpace;
  348.             HandleDragHilite(kHiliteInit, &iconRect, &textRect);
  349.             
  350.             // let the drag manager know if we can't accept this drag
  351.             if (!(gpFWXAppData->dragHandlerGlobals).acceptableDragFlag)
  352.                 err = dragNotAcceptedErr;
  353.             break;
  354.             
  355.         case dragTrackingEnterWindow: 
  356.         case dragTrackingInWindow:
  357.         case dragTrackingLeaveWindow:            
  358.             // Handle highlighting the receive node icon
  359.             if (gpFWXAppData->dragHandlerGlobals.acceptableDragFlag)
  360.             {
  361.                 pWinData = (WindowDataPtr) GetWRefCon(pWin);
  362.                 deltaH = GetControlValue(pWinData->hHScrollBar);
  363.                 deltaV = GetControlValue(pWinData->hVScrollBar);
  364.                 SetOrigin(deltaH, deltaV);
  365.                 GetClip(hOldClip = NewRgn());
  366.                 drawRect = pWin->portRect;
  367.                 drawRect.bottom -= kScrollBarAdjust;
  368.                 drawRect.right -= kScrollBarAdjust;
  369.                 ClipRect(&drawRect);
  370.                 
  371.                 // Unless the mouse is leaving the visible area of the
  372.                 // window, check if it's in the window's content region
  373.                 if (theMessage == dragTrackingLeaveWindow)
  374.                     mouseInWhichSpace = kNoSpace;
  375.                 else
  376.                 {
  377.                     GetDragMouse(theDrag, &localPt, nil);
  378.                     GlobalToLocal(&localPt);
  379.                     mouseInWhichSpace = WhichRecvNode(pWin, localPt);
  380.                 }
  381.  
  382.                 // If the mouse's space is not equal to the hilitedSpace
  383.                 // and the mouse is in a space  (i.e., a new, different space.)
  384.                 if ((mouseInWhichSpace != gpFWXAppData->dragHandlerGlobals.hilitedSpace) &&
  385.                     (mouseInWhichSpace != kNoSpace))
  386.                 {
  387.                     if (gpFWXAppData->dragHandlerGlobals.hilitedSpace != kNoSpace)
  388.                     {        
  389.                         // There is a currently hilited space, unhilite it
  390.                         GetNodeDragRect (pWin,
  391.                                          gpFWXAppData->dragHandlerGlobals.hilitedSpace,
  392.                                          &iconRect,
  393.                                          &textRect);
  394.                         HandleDragHilite(kHiliteOff, &iconRect, &textRect);
  395.                     }
  396.  
  397.                     // draw the hilight
  398.                     GetNodeDragRect(pWin, mouseInWhichSpace, &iconRect, &textRect);
  399.                     HandleDragHilite(kHiliteOn, &iconRect, &textRect);
  400.                     gpFWXAppData->dragHandlerGlobals.hilitedSpace = mouseInWhichSpace;                    
  401.                 }
  402.                 // else if the mouse is not in the content region
  403.                 // and an icon is hilighted, erase the hilight
  404.                 else if ((mouseInWhichSpace == kNoSpace) &&
  405.                          (gpFWXAppData->dragHandlerGlobals.hilitedSpace != kNoSpace))
  406.                 {
  407.                     GetNodeDragRect (pWin,
  408.                                      gpFWXAppData->dragHandlerGlobals.hilitedSpace,
  409.                                      &iconRect,
  410.                                      &textRect);
  411.                     HandleDragHilite(kHiliteOff, &iconRect, &textRect);
  412.                     gpFWXAppData->dragHandlerGlobals.hilitedSpace = kNoSpace;
  413.                 }
  414.                 SetOrigin(0, 0);
  415.                 SetClip(hOldClip);
  416.                 DisposeRgn(hOldClip);
  417.             }
  418.             break;
  419.  
  420.         // do nothing for the leaveHandler message
  421.         case dragTrackingLeaveHandler:
  422.             HandleDragHilite(kHiliteDispose, &iconRect, &textRect);
  423.             break;
  424.         
  425.         // let the drag manager know if we didn't recognize the message
  426.         default:
  427.             err = paramErr;
  428.     }
  429.     return err;
  430. }
  431.  
  432. //////////////////////////////////////////////////////////////////////////////
  433. //
  434. //    HandleDragHilite
  435. //
  436. //    Handle hiliting of node icons in sender window
  437. static void HandleDragHilite (
  438.     SInt16                theMessage,
  439.     Rect                *iconRect,
  440.     Rect                *textRect)
  441. {
  442.     static Handle        hIconSuite;
  443.     OSErr                err;
  444.  
  445.     switch (theMessage)
  446.     {
  447.         case kHiliteInit:
  448.             err = GetIconSuite(&hIconSuite, kDropIconSuiteID, svAllAvailableData);
  449.             break;
  450.         case kHiliteOff:
  451.             err = PlotIconSuite(iconRect, atNone, ttNone, hIconSuite);
  452.             InvertRect(textRect);
  453.             break;
  454.         case kHiliteOn:
  455.             err = PlotIconSuite(iconRect, atNone, ttSelected, hIconSuite);
  456.             InvertRect(textRect);
  457.             break;
  458.         case kHiliteDispose:
  459.             err = DisposeIconSuite(hIconSuite, false);
  460.     }
  461. }
  462.  
  463. //////////////////////////////////////////////////////////////////////////////
  464. //
  465. //    HandleDragReceive
  466. //
  467. //    Called by the drag manager when a drag ends in our window
  468. //
  469. //    Need to loop through each drag item and get its hfs data
  470. //    building a list of fsspec's as we go.
  471. //
  472. //    Send an AppleEvent to ourselves to handle copying the list.
  473. //
  474.  
  475. static pascal OSErr HandleDragReceive (
  476.     WindowPtr                pWin,
  477.     void                    *handlerRefCon, 
  478.     DragReference            theDrag)
  479. {
  480. //#pragma unused handlerRefCon
  481.     
  482.     ItemReference            itemRef;
  483.     Size                    flavorDataSize;
  484.     FSSpecPtr                pFSSpecList;
  485.     HFSFlavor                itemHFSFlavor;
  486.     UInt16                    numItems;
  487.     UInt16                    indexItem;
  488.     OSErr                    err = noErr;
  489.     
  490.     if (! (DragItemsAreAcceptable(theDrag) && MouseIsInContentRgn(theDrag, pWin)))
  491.         return dragNotAcceptedErr;
  492.  
  493.     err = CountDragItems(theDrag, &numItems);
  494.     if (err == noErr)
  495.     {
  496.         //    allocate a buffer to grab each of the drag items FSSpecs
  497.         pFSSpecList = (FSSpecPtr) NewPtr(sizeof(FSSpec) * numItems);
  498.         if (pFSSpecList == nil)
  499.             return memFullErr;
  500.         
  501.         for (indexItem = 1; indexItem <= numItems; indexItem++) {
  502.             // reset flavorDataSize through each loop
  503.             // as it gets updated by the GetFlavorData call
  504.             flavorDataSize = sizeof(HFSFlavor);
  505.             
  506.             err = GetDragItemReferenceNumber(theDrag, indexItem, &itemRef);
  507.             if (err != noErr) {
  508.                 DisposePtr((Ptr)pFSSpecList);
  509.                 return err;
  510.             }
  511.             
  512.             err = GetFlavorData(theDrag, itemRef, flavorTypeHFS, 
  513.                                 &itemHFSFlavor, &flavorDataSize, 0);
  514.             if (err != noErr) {
  515.                 DisposePtr((Ptr)pFSSpecList);
  516.                 return err;
  517.             }
  518.             pFSSpecList[indexItem-1] = itemHFSFlavor.fileSpec;
  519.         }
  520.         if (err == noErr)
  521.             SendDropInWindowRecvNode(pWin, theDrag, pFSSpecList, numItems);
  522.  
  523.         DisposePtr((Ptr)pFSSpecList);
  524.     }
  525.     return err;
  526. }
  527.  
  528. //////////////////////////////////////////////////////////////////////////////
  529. //
  530. //    SendSetterToSelf
  531. //
  532. //    Send an AppleEvent to ourself with the firewire file exchange
  533. //    receive node ID and the FSSpec list of items to be sent.
  534. //
  535.  
  536. OSErr SendFSSpecListToSelf (
  537.     FWXNodeID                fwxNodeID,
  538.     FSSpecPtr                pFSSpecList,
  539.     UInt16                    numFSSpecs)
  540. {
  541.     AppleEvent                send;
  542.     AppleEvent                reply;
  543.     AEDesc                    selfTarget;
  544.     ProcessSerialNumber        psn;
  545.     UInt32                    longFSSpecCount;
  546.     OSErr                    err;
  547.  
  548.     longFSSpecCount = numFSSpecs;
  549.     selfTarget.dataHandle = nil;
  550.     send.dataHandle = nil;
  551.  
  552.     GetCurrentProcess(&psn);
  553.     err = AECreateDesc(typeProcessSerialNumber, (Ptr) &psn, sizeof(ProcessSerialNumber), &selfTarget);
  554.     if (err != noErr)
  555.         return err;
  556.     
  557.     err = AECreateAppleEvent(kAEFWXEventClass, kAEFileSpecList, &selfTarget, 
  558.             kAutoGenerateReturnID, kAnyTransactionID, &send);
  559.     if (err != noErr) {
  560.         AEDisposeDesc(&selfTarget);
  561.         return err;
  562.     }
  563.         
  564.     err = AEPutParamPtr(&send, kAEFWXNodeIDKey, kAEFWXNodeIDType, (Ptr) &fwxNodeID, sizeof(FWXNodeID));
  565.     if (err != noErr) {
  566.         AEDisposeDesc(&selfTarget);
  567.         if (send.dataHandle != nil)
  568.             AEDisposeDesc(&send);
  569.         return err;
  570.     }
  571.  
  572.     err = AEPutParamPtr(&send, kAEFSSpecKey, typeFSS, (Ptr) pFSSpecList, sizeof(FSSpec)*numFSSpecs);
  573.     if (err != noErr) {
  574.         AEDisposeDesc(&selfTarget);
  575.         if (send.dataHandle != nil)
  576.             AEDisposeDesc(&send);
  577.         return err;
  578.     }
  579.     
  580.     err = AEPutParamPtr(&send, kAEFSSpecCountKey, typeLongInteger, (Ptr) &longFSSpecCount, sizeof(UInt32));
  581.     if (err != noErr) {
  582.         AEDisposeDesc(&selfTarget);
  583.         if (send.dataHandle != nil)
  584.             AEDisposeDesc(&send);
  585.         return err;
  586.     }
  587.  
  588.     err = AESend(&send, &reply, kAENoReply + kAEAlwaysInteract + kAECanSwitchLayer,
  589.                 kAENormalPriority, kAEDefaultTimeout, nil, nil);
  590.  
  591.     if (err != noErr) {
  592.         AEDisposeDesc(&selfTarget);
  593.         AEDisposeDesc(&send);
  594.     }
  595.  
  596.     return err;
  597. }
  598.  
  599. //////////////////////////////////////////////////////////////////////////////
  600. //
  601. //    GetNodeInfo
  602. //
  603. //    Return the nodeInfo record for the node id.
  604. //
  605.  
  606. OSErr GetNodeInfo (
  607.     FWXNodeID            nodeID,
  608.     RecvNodePtr            *pRecvNode)
  609. {
  610.     WindowPtr            pWin;
  611.     WindowDataPtr        pWinData;
  612.     RecvNodePtr            pTempRecvNode;
  613.     SInt16                index;
  614.     OSErr                err = noErr;
  615.     
  616.     pWin = gpFWXAppData->pSenderWindow;
  617.     pWinData = (WindowDataPtr) GetWRefCon(pWin);
  618.         
  619.     pTempRecvNode = pWinData->pRecvNodeList;
  620.     for (index = 0; index < pWinData->numRecvNodes; index++) {
  621.         if (pTempRecvNode->nodeID == nodeID)
  622.             break;
  623.         pTempRecvNode = (RecvNodePtr) pTempRecvNode->pNextNode;
  624.     }
  625.  
  626.     *pRecvNode = pTempRecvNode;
  627.     if (pTempRecvNode == nil)
  628.         err = resNotFound;     // JKL *** what error?
  629.  
  630.     return err;
  631. }
  632.  
  633.  
  634. //////////////////////////////////////////////////////////////////////////////
  635. //
  636. //    GetNodeName
  637. //
  638. //    Get the bounding rectangle of a drag area for the specified index.
  639. //    There is a drag area for each FireWire Exchange node.
  640. //
  641.  
  642. OSErr GetNodeName (
  643.     WindowPtr            pWin,
  644.     SInt16                nodeIndex,
  645.     StringPtr            *pString)
  646. {
  647.     WindowDataPtr        pWinData;
  648.     RecvNodePtr            pTempRecvNode;
  649.     SInt16                index;
  650.     
  651.     pWinData = (WindowDataPtr) GetWRefCon(pWin);
  652.     if (nodeIndex > pWinData->numRecvNodes)
  653.         return memFullErr;        // JKL - some error
  654.         
  655.     pTempRecvNode = pWinData->pRecvNodeList;
  656.     for (index = 1; index < nodeIndex; index++) {
  657.         pTempRecvNode = (RecvNodePtr) pTempRecvNode->pNextNode;
  658.     }
  659.  
  660.     *pString = pTempRecvNode->nodeName;
  661.  
  662.     return noErr;
  663. }
  664.  
  665.  
  666. //////////////////////////////////////////////////////////////////////////////
  667. //
  668. //    GetNodeDragRect
  669. //
  670. //    Get the bounding rectangle of a drag area for the specified index.
  671. //    There is a drag area for each FireWire Exchange node.
  672. //
  673.  
  674. OSErr GetNodeDragRect (
  675.     WindowPtr            pWin,
  676.     SInt16                nodeIndex,
  677.     Rect                *iconRect,
  678.     Rect                *textRect)
  679. {
  680.     WindowDataPtr        pWinData;
  681.     RecvNodePtr            pTempRecvNode;
  682.     SInt16                index;
  683.     
  684.     pWinData = (WindowDataPtr) GetWRefCon(pWin);
  685.     if (nodeIndex > pWinData->numRecvNodes)
  686.         return memFullErr;        // JKL - some error
  687.         
  688.     pTempRecvNode = pWinData->pRecvNodeList;
  689.     for (index = 1; index < nodeIndex; index++) {
  690.         pTempRecvNode = (RecvNodePtr) pTempRecvNode->pNextNode;
  691.     }
  692.  
  693.     *iconRect = pTempRecvNode->recvNodeIconRect;
  694.     *textRect = pTempRecvNode->recvNodeTextRect;
  695.  
  696.     return noErr;
  697. }
  698.  
  699.  
  700. //////////////////////////////////////////////////////////////////////////////
  701. //
  702. //    WhichRecvNode
  703. //
  704. //    Determine where the drop has taken place. There is a space for each
  705. //    FireWire Exchange node. After doing a compare it will return the space
  706. //    number, or kNoSpace if it didn't land in a space.
  707. //
  708.  
  709. SInt16 WhichRecvNode (
  710.     WindowPtr            pWin,
  711.     Point                localPt)
  712. {
  713.     WindowDataPtr        pWinData;
  714.     RgnHandle            iconRgn, textRgn, dragRgn;
  715.     Rect                iconRect;
  716.     Rect                textRect;
  717.     SInt16                count;
  718.     SInt16                theNodeIndex;
  719.     
  720.     pWinData = (WindowDataPtr) GetWRefCon(pWin);
  721.     theNodeIndex = kNoSpace;
  722.     if (pWinData == nil)
  723.         return theNodeIndex;
  724.     
  725.     iconRgn = NewRgn();
  726.     textRgn = NewRgn();
  727.     dragRgn = NewRgn();
  728.     if (pWinData != nil)
  729.     {
  730.         for (count = 1; count <= pWinData->numRecvNodes; count ++)
  731.         {            
  732.             GetNodeDragRect(pWin, count, &iconRect, &textRect);
  733.             RectRgn(iconRgn, &iconRect);
  734.             RectRgn(textRgn, &textRect);
  735.             UnionRgn(iconRgn, textRgn, dragRgn);
  736.             if (PtInRgn(localPt, dragRgn))
  737.             {
  738.                 theNodeIndex = count;
  739.                 break;
  740.             }
  741.         }
  742.     }
  743.     DisposeRgn(iconRgn);
  744.     DisposeRgn(textRgn);
  745.     DisposeRgn(dragRgn);
  746.     return theNodeIndex;
  747. }
  748.  
  749. //////////////////////////////////////////////////////////////////////////////
  750. //
  751. //    GetNodeIDFromIndex
  752. //
  753. //    Using an index into the list of receive nodes, get the FireWire File
  754. //    Exchange node id from the indexed node.
  755. //
  756.  
  757. static void GetNodeIDFromIndex(
  758.     SInt16                nodeIndex,
  759.     FWXNodeID            *whichNode,
  760.     WindowPtr            pWin)
  761. {
  762.     WindowDataPtr        pWinData;
  763.     RecvNodePtr            pTempRecvNode;
  764.     SInt16                i;
  765.     
  766.     pWinData = (WindowDataPtr) GetWRefCon(pWin);
  767.     *whichNode = kInvalidFWXNodeID;
  768.     
  769.     if (pWinData != nil) {
  770.         
  771.         if (nodeIndex <= pWinData->numRecvNodes) {
  772.             pTempRecvNode = pWinData->pRecvNodeList;
  773.             for (i = 1; i < nodeIndex; i++) {
  774.                 pTempRecvNode = (RecvNodePtr) pTempRecvNode->pNextNode;
  775.             }
  776.     
  777.             *whichNode = pTempRecvNode->nodeID;
  778.         }
  779.     }
  780. }
  781.         
  782. //////////////////////////////////////////////////////////////////////////////
  783. //
  784. //    SendDropInWindowRecvNode
  785. //
  786. //    Get the drag location, convert it to local coordinates. Find which receive
  787. //    node the drop occurred in and send us an AppleEvent with the list of FSSpec's.
  788. //
  789.  
  790. static void SendDropInWindowRecvNode (
  791.     WindowPtr            pWin,
  792.     DragReference        theDrag,
  793.     FSSpecPtr            pFSSpecList,
  794.     UInt16                numInList)
  795. {
  796.     Point                 thePoint;
  797.     GrafPtr                oldPort;
  798.     FWXNodeID            whichFWXNode = (FWXNodeID) kInvalidFWXNodeID;
  799.     SInt16                theNodeIndex;
  800.     OSErr                err;
  801.  
  802.     GetPort(&oldPort);
  803.     SetPort(pWin);
  804.     GetDragMouse(theDrag, &thePoint, 0L);
  805.     GlobalToLocal(&thePoint);
  806.     theNodeIndex = WhichRecvNode(pWin, thePoint);
  807.     SetPort(oldPort);
  808.     
  809.     if (theNodeIndex != kNoSpace)
  810.         GetNodeIDFromIndex(theNodeIndex, &whichFWXNode, pWin);
  811.  
  812.     if (whichFWXNode != (FWXNodeID) kInvalidFWXNodeID)
  813.         err = SendFSSpecListToSelf(whichFWXNode, pFSSpecList, numInList);
  814. }
  815.  
  816. //////////////////////////////////////////////////////////////////////////////
  817. //
  818. //    HandleAEFileSpecList
  819. //
  820. //    Pull parameters out of AppleEvent and call routine to handle the drop.
  821. //
  822.  
  823. pascal OSErr HandleAEFileSpecList (
  824.     AppleEvent            *pAEvent,
  825.     AppleEvent             *pReply,
  826.     SInt32                refCon)
  827. {
  828. //#pragma unused pReply
  829. //#pragma unused refCon
  830.  
  831.     OSErr                err;
  832.     DescType            returnType;
  833.     Size                returnSize;
  834.     FWXNodeID            whichNode;
  835.     UInt32                numFSSpecs;
  836.     FSSpecPtr            pFSSpec;
  837.     UInt16                index;
  838.  
  839.     err = AEGetParamPtr(pAEvent, kAEFWXNodeIDKey, kAEFWXNodeIDType, &returnType,
  840.                         (Ptr) &whichNode, sizeof(FWXNodeID), &returnSize);
  841.     if (err != noErr)
  842.         return err;
  843.  
  844.     err = AEGetParamPtr(pAEvent, kAEFSSpecCountKey, typeLongInteger, &returnType,
  845.                         (Ptr) &numFSSpecs, sizeof(SInt32), &returnSize);
  846.     if (err != noErr)
  847.         return err;
  848.  
  849.     pFSSpec = (FSSpecPtr) NewPtr(sizeof(FSSpec) * numFSSpecs);
  850.     if (pFSSpec == nil)
  851.         return memFullErr;
  852.         
  853.     err = AEGetParamPtr(pAEvent, kAEFSSpecKey, typeFSS, &returnType,
  854.                         (Ptr) pFSSpec, sizeof(FSSpec) * numFSSpecs, &returnSize);
  855.     if (err != noErr)
  856.         return err;
  857.  
  858.     for (index = 0; index < numFSSpecs; index++) {
  859.         err = HandleFSItem(&pFSSpec[index], whichNode);
  860.         if (err != noErr) {
  861.             sprintf(debugStr, "Error in HandleFileList: %d", err);
  862.             FWDebugStr((ConstStr255Param) c2pstr(debugStr));
  863.             break;
  864.         }
  865.     }
  866.     
  867.     DisposePtr((Ptr) pFSSpec);
  868.     
  869.     return err;
  870. }
  871.